package me.aip.mov.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import me.aip.mov.constant.Constant;
import me.aip.mov.entity.AccessUser;
import me.aip.mov.entity.UserInfo;
import me.aip.mov.exception.ServiceException;
import me.aip.mov.response.ResponseResult;
import me.aip.mov.service.IAuthService;
import me.aip.mov.service.IUserInfoService;
import me.aip.mov.util.JwtUtil;
import me.aip.mov.util.RSACoder;
import me.aip.mov.util.RandomUtil;
import me.aip.mov.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
public class AuthServiceImpl implements IAuthService {
    @Autowired
    IUserInfoService userService;

    @Override
    public Map<String, String> getRsakey() throws Exception  {
        String rsakey = "RSAKEY" + RandomUtil.getRandomChars(24);
        Map map = RSACoder.initKey();
        String publicKey = RSACoder.getPublicKey(map);
        String privateKey = RSACoder.getPrivateKey(map);
        RedisUtil.StringOps.setEx(rsakey,privateKey,120L, TimeUnit.SECONDS);
        Map<String, String> rsaKeyMap = new HashMap<>(2);
        rsaKeyMap.put("publicKey", publicKey);
        rsaKeyMap.put("rsakey", rsakey);
        return rsaKeyMap;
    }
    @Override
    public UserInfo loginByPhone(AccessUser accessUser) {
        UserInfo user = userService.getUserByUsername(accessUser.getPhone());
        final String salt = RandomUtil.generateRandomString(8);
        final String userPwdMd5 = DigestUtils.md5DigestAsHex((accessUser.getPasswd() + salt).getBytes());
        return null;
    }

    @Override
    public String getDecodePassword(String passwd, String rsakey) {
        if (StringUtils.isBlank(rsakey)) {
            return null;
        }
        String privateKey = RedisUtil.StringOps.get(rsakey);
        if (privateKey == null) {
            return null;
        }
        try {
            return RSACoder.privateKeyDecrypt(passwd, privateKey);
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public ResponseResult login(String userName, String passwd) {
        UserInfo user = userService.getUserByUsername(userName);
        if (user == null){
            throw new ServiceException("用户不存在！");
        }
        if (validatePwd(passwd,user.getPassword(),user.getSalt())){
            String token = JwtUtil.sign(user.getUserId(), user.getPassword());
            Map<String,String> map= new HashMap<>();
            map.put("token",token);
            map.put("userId",user.getUserId());
            map.put("user", JSON.toJSONString(user));
            String tokenKey = Constant.Redis.TOKEN_PREFIX + token;
            RedisUtil.StringOps.setEx(tokenKey, token, 30 * 365 , TimeUnit.DAYS);
            return ResponseResult.success(map);
        }
        throw new ServiceException("密码不正确！");
    }

    @Override
    public ResponseResult loginByWx(String wxCode, String appId) {
        return null;
    }

    @Override
    public ResponseResult loginByWxApplet(String wxCode, String appId, String encryptedData, String iv) {
        return null;
    }

    @Override
    public ResponseResult loginByQQ(String openId, String unionid, String nickName, String city, String province, String headimgurl, String sex) {
        return null;
    }

    @Override
    public ResponseResult loginByApple(String openId, String unionid, String nickName) {
        return null;
    }

    @Override
    public ResponseResult getOpenInfo(String wxCode, String appId) {
        return null;
    }

    @Override
    public ResponseResult getOpenInfoJS(String wxCode, String appId) {
        return null;
    }

    @Override
    public boolean validateSmsCode(String tel, String smsCode) {
        return false;
    }

    @Override
    public ResponseResult creatUserByWx(String tel, String wxCode, String source) {
        return null;
    }

    @Override
    public ResponseResult loginBySms(String tel) {
        return null;
    }

    @Override
    public ResponseResult creatUserByPhone(String tel, String passwd, String source) {
        final String salt = RandomUtil.generateRandomString(8);
        final String userPwdMd5 = DigestUtils.md5DigestAsHex((passwd + salt).getBytes());
        UserInfo userInfo = UserInfo.builder().phone(tel).password(userPwdMd5).salt(salt).build();
        userService.save(userInfo);
        return ResponseResult.success();
    }
    @Override
    public ResponseResult creatUserByUserName(String userName, String passwd, String source) {
        final String salt = RandomUtil.generateRandomString(8);
        final String userPwdMd5 = DigestUtils.md5DigestAsHex((passwd + salt).getBytes());
        String promoCode = createPromoCode();

        UserInfo userInfo = UserInfo.builder().userName(userName).nickName("用户"+promoCode).password(userPwdMd5).promoCode(promoCode).salt(salt).build();
        userService.save(userInfo);
        return ResponseResult.success();
    }
    private String createPromoCode(){
        String code = RandomUtil.getRandomChars(10);
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(UserInfo::getPromoCode,code);
        int count = userService.count(queryWrapper);
        if (count>0){
            return createPromoCode();
        }
        return code;
    }
    @Override
    public ResponseResult forgetPassword(String tel, String passwd) {
        return null;
    }

    @Override
    public ResponseResult changePassword(String userId, String passwd, String smsCode) {
        return null;
    }

    @Override
    public void outLogin(String token) {

    }

    @Override
    public ResponseResult sendSms(String tel) {
        return null;
    }

    @Override
    public boolean validateCaptchaCode(String captchaCode) {
        return false;
    }


    private boolean validatePwd(final String userPwd, final String pwd, final String salt) {
        final String userPwdMd5 = DigestUtils.md5DigestAsHex((userPwd + salt).getBytes());
        return userPwdMd5.equals(pwd);
    }
}
